package com.wksc.framework.impexp.task;

import com.wksc.framework.impexp.constants.TaskStat;
import com.wksc.framework.impexp.log.ImpExpLog;
import com.wksc.framework.impexp.result.BaseResult;
import com.wksc.framework.impexp.result.StatObserver;
import com.wksc.framework.impexp.template.BaseTemplate;
import com.wksc.framework.impexp.thread.TaskManage;
import com.wksc.framework.impexp.util.ClassFactory;
import jxl.read.biff.BiffException;
import jxl.write.WriteException;

import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Observable;
import java.util.concurrent.Callable;


/**
 * <p>
 * Title(文件名): Task.java
 * </p>
 * <p>
 * Description(描述): 导入导出任务的基类
 * </p>
 * <p>
 * Copyright(版权): Copyright (c) 2011
 * </p>
 * <p>
 * Company(公司): 成都四方信息技术有限公司
 * </p>
 * <p>
 * CreateTime(生成日期)：2011-10-20下午03:17:13
 * </p>
 *
 * @author wanglei
 * @version impExp_C13
 */
public abstract class Task extends Observable implements Callable<BaseResult>,
        Serializable {
    private static final long serialVersionUID = -6307000367564333604L;

    protected ImpExpLog log;

    /**
     * 执行任务所需的模板
     */
    protected BaseTemplate baseTemplate;

    /**
     * 任务执行状态
     */
    //设为private使子类只能通过setTaskStat方法来改变此属性值
    private TaskStat taskStat;

    /**
     * 任务执行过程中是否中断过
     */
    protected boolean cancelTask = false;

    /**
     * 导入导出执行结果
     */
    protected BaseResult result;

    /**
     * Task的无参构造函数
     *
     * @param baseTemplate 基类模板
     * @throws ClassNotFoundException 初始化时设置任务类型时为找到对应Class异常, 异常往上抛出
     */
    public Task(BaseTemplate baseTemplate) throws ClassNotFoundException {
        //为当前对象添加观察者
        this.addObserver(new StatObserver());
        this.baseTemplate = baseTemplate;

        //建立任务时的一些初始化工作
        init();
    }

    /**
     * 方法描述：Task类的一些初始化工作,子类可重写添加子类自己的初始化内容
     *
     * @throws ClassNotFoundException 初始化时设置任务类型时为找到对应Class异常, 异常往上抛出
     * @creator wanglei
     */
    protected void init() throws ClassNotFoundException {
        //初始化日志对象
        log = ClassFactory.getLog(getClass());

		/*
         * 根据任务包含的BaseTemplate具体实例初始化任务类型TaskType属性
		 * getTaskType会抛出异常
		 */
        //baseTemplate.setTaskType(ImpExpTools.getTaskType(baseTemplate));

        //设定任务状态为新建
        setTaskStat(TaskStat.TASK_CREATED);
    }

    /**
     * 导入导出的具体业务处理过程,由子类实现,任务结束后返回执行结果
     */
    public BaseResult call() {
        //将任务状态更改为"开始执行"
        setTaskStat(TaskStat.TASK_RUNNING); //job_state改为2

        //不同任务具体的处理过程
        try {
            process();
            //将任务状态更改为"结束"
            if (cancelTask) {
                setTaskStat(TaskStat.TASK_CANCELLED);
            } else if (ClassFactory.getImpExpDao().getQueueSize(
                    this.getBaseTemplate().getFileName(),
                    TaskStat.TASK_CANCELLED, taskStat.TASK_CANCELLING) > 0) {

                setTaskStat(TaskStat.TASK_CANCELLED);
                TaskManage.cancelTask(this.getBaseTemplate().getFileName()); //通知自己的cancel任务
            } else {
                ClassFactory.getImpExpDao().syncCurrentState(
                        this.getBaseTemplate().getFileName()); //将current_state改为job_state
                setTaskStat(TaskStat.TASK_FINISHED); //将job_state改为3
                log.debug("Job finished, name:"
                        + this.getBaseTemplate().getFileName() + ",ip:"
                        + this.getBaseTemplate().getIp());
            }
        } catch (InterruptedException e) {
            result.setResultMsg(ClassFactory.getI18n().getInterruptedinfo());
            setTaskStat(TaskStat.TASK_EXCEPTION);
        } catch (SQLException sqlEx) {
            result.setResultMsg(ClassFactory.getI18n().getSqlexceptioninfo());
            setTaskStat(TaskStat.TASK_EXCEPTION);
            sqlEx.printStackTrace();
        } catch (IOException fileEx) {
            result.setResultMsg(ClassFactory.getI18n().getIoexceptioninfo());
            setTaskStat(TaskStat.TASK_EXCEPTION);
            fileEx.printStackTrace();
        } catch (Exception ex) {
            result.setResultMsg(ClassFactory.getI18n().getExceptioninfo());
            setTaskStat(TaskStat.TASK_EXCEPTION);
            ex.printStackTrace();
        } finally {
            //其他清理工作
        }
        return result;
    }

    /**
     * 方法描述：导入导出操作不同的业务实现,此方法具体处理内容由子类重写
     *
     * @throws java.sql.SQLException 数据库异常
     * @throws InterruptedException  中断异常
     * @throws Exception             其他异常
     * @creator wanglei
     */
    protected abstract void process() throws InterruptedException,
            SQLException, Exception;

    /**
     * 方法描述：检查当前任务的中断情况,如果线程被中断抛出InterruptedException
     *
     * @return <p>
     * true - 检测到取消请求; false - 未检测到取消请求
     * </p>
     * @throws java.io.IOException
     * @throws WriteException
     * @throws BiffException
     * @creator wanglei
     */
    protected boolean checkInterrupted() throws BiffException, WriteException,
            IOException {
        if (cancelTask) {
            result.setTaskCancelled(cancelTask);
            beforeExit();
            return true;
        } else if (ClassFactory.getImpExpDao().getQueueSize(
                this.getBaseTemplate().getFileName(), TaskStat.TASK_CANCELLED, taskStat.TASK_CANCELLING) > 0) {
            result.setTaskCancelled(cancelTask);
            beforeExit();
            TaskManage.cancelTask(this.getBaseTemplate().getFileName()); //通知自己的cancel任务
            return true;
        } else {
            return false;
        }
    }

    /**
     * 方法描述：检测到取消中断请求后处理result结果的处理方法
     * 由导入或导出方法实现
     *
     * @throws java.io.IOException
     * @throws WriteException
     * @throws BiffException
     * @creator wanglei
     */
    protected abstract void beforeExit() throws BiffException, WriteException,
            IOException;

    /**
     * 方法描述：取消任务执行时为任务设置取消标识
     *
     * @creator wanglei
     */
    public abstract void cancelTask();

	/* =========setters & getters============== */

    public TaskStat getTaskStat() {
        return taskStat;
    }

    public void setTaskStat4DbAndMem(TaskStat taskStat) {
        if (!ClassFactory.getImpExpDao().updateTaskCurrentState(this, taskStat)) {
            return;
        }
        this.setTaskStat(taskStat);
    }

    /**
     * 方法描述：设置任务的状态属性,供子类调用
     *
     * @param taskStat
     * @creator wanglei
     */
    public void setTaskStat(TaskStat taskStat) {
        this.taskStat = taskStat;
        //		return ClassFactory.getImpExpDao().getQueueSize(null,
        //				TaskStat.TASK_RUNNING);
        //任务状态发生改变后通知观察者
        setChanged();
        notifyObservers(baseTemplate);
    }

    public BaseTemplate getBaseTemplate() {
        return baseTemplate;
    }

    public void setBaseTemplate(BaseTemplate baseTemplate) {
        this.baseTemplate = baseTemplate;
    }

    public BaseResult getResult() {
        return result;
    }

    protected void setResult(BaseResult result) {
        this.result = result;
    }

    public boolean isCancelTask() {
        return cancelTask; //使用内存和短路运算减少查库次数
    }

    public void setCancelTask(boolean cancelTask) {
        ClassFactory.getImpExpDao().updateTaskCurrentState(this,
                TaskStat.TASK_CANCELLED);
        this.cancelTask = cancelTask;
    }
	/* =========setters & getters============== */
}
